import { Component } from '../core/Component';
import { GameObject } from '../core/GameObject';
import { InputManager } from './InputManager';
import { InputEventType, InputEventData, InputEventHandler, TouchPoint } from './types';

/**
 * 输入组件基类
 * 用于处理游戏对象的输入事件
 */
export abstract class InputComponent extends Component {
    protected inputManager: InputManager;
    private eventHandlers: Map<InputEventType, InputEventHandler>;
    
    constructor(gameObject: GameObject, inputManager: InputManager) {
        super(gameObject);
        
        this.inputManager = inputManager;
        this.eventHandlers = new Map();
    }
    
    /**
     * 添加输入事件处理器
     */
    protected addInputHandler(type: InputEventType, handler: InputEventHandler): void {
        this.eventHandlers.set(type, handler);
        this.inputManager.addEventListener(type, handler);
    }
    
    /**
     * 移除输入事件处理器
     */
    protected removeInputHandler(type: InputEventType): void {
        const handler = this.eventHandlers.get(type);
        if (handler) {
            this.inputManager.removeEventListener(type, handler);
            this.eventHandlers.delete(type);
        }
    }
    
    /**
     * 移除所有输入事件处理器
     */
    protected removeAllInputHandlers(): void {
        this.eventHandlers.forEach((handler, type) => {
            this.inputManager.removeEventListener(type, handler);
        });
        this.eventHandlers.clear();
    }
    
    /**
     * 组件销毁时清理事件处理器
     */
    public destroy(): void {
        this.removeAllInputHandlers();
        super.destroy();
    }
}

/**
 * 键盘输入组件
 * 用于处理游戏对象的键盘输入
 */
export class KeyboardInputComponent extends InputComponent {
    private keyHandlers: Map<string, (isPressed: boolean) => void>;
    
    constructor(gameObject: GameObject, inputManager: InputManager) {
        super(gameObject, inputManager);
        
        this.keyHandlers = new Map();
        
        // 添加键盘事件处理器
        this.addInputHandler(InputEventType.KEY_DOWN, this.handleKeyEvent);
        this.addInputHandler(InputEventType.KEY_UP, this.handleKeyEvent);
    }
    
    /**
     * 添加按键处理器
     */
    public onKey(key: string, handler: (isPressed: boolean) => void): void {
        this.keyHandlers.set(key.toLowerCase(), handler);
    }
    
    /**
     * 移除按键处理器
     */
    public offKey(key: string): void {
        this.keyHandlers.delete(key.toLowerCase());
    }
    
    /**
     * 检查按键是否被按下
     */
    public isKeyPressed(key: string): boolean {
        return this.inputManager.isKeyPressed(key);
    }
    
    /**
     * 处理键盘事件
     */
    private handleKeyEvent = (event: InputEventData): void => {
        if (!event.key) return;
        
        const key = event.key.toLowerCase();
        const handler = this.keyHandlers.get(key);
        
        if (handler) {
            handler(event.type === InputEventType.KEY_DOWN);
        }
    };
    
    /**
     * 组件销毁时清理按键处理器
     */
    public destroy(): void {
        this.keyHandlers.clear();
        super.destroy();
    }
}

/**
 * 鼠标输入组件
 * 用于处理游戏对象的鼠标输入
 */
export class MouseInputComponent extends InputComponent {
    private buttonHandlers: Map<number, (isPressed: boolean) => void>;
    private moveHandler: ((x: number, y: number) => void) | null;
    private wheelHandler: ((delta: number) => void) | null;
    
    constructor(gameObject: GameObject, inputManager: InputManager) {
        super(gameObject, inputManager);
        
        this.buttonHandlers = new Map();
        this.moveHandler = null;
        this.wheelHandler = null;
        
        // 添加鼠标事件处理器
        this.addInputHandler(InputEventType.MOUSE_DOWN, this.handleMouseEvent);
        this.addInputHandler(InputEventType.MOUSE_UP, this.handleMouseEvent);
        this.addInputHandler(InputEventType.MOUSE_MOVE, this.handleMouseEvent);
        this.addInputHandler(InputEventType.MOUSE_WHEEL, this.handleMouseEvent);
    }
    
    /**
     * 添加鼠标按钮处理器
     */
    public onMouseButton(button: number, handler: (isPressed: boolean) => void): void {
        this.buttonHandlers.set(button, handler);
    }
    
    /**
     * 移除鼠标按钮处理器
     */
    public offMouseButton(button: number): void {
        this.buttonHandlers.delete(button);
    }
    
    /**
     * 设置鼠标移动处理器
     */
    public onMouseMove(handler: (x: number, y: number) => void): void {
        this.moveHandler = handler;
    }
    
    /**
     * 设置鼠标滚轮处理器
     */
    public onMouseWheel(handler: (delta: number) => void): void {
        this.wheelHandler = handler;
    }
    
    /**
     * 检查鼠标按钮是否被按下
     */
    public isMouseButtonPressed(button: number): boolean {
        return this.inputManager.isMouseButtonPressed(button);
    }
    
    /**
     * 获取鼠标位置
     */
    public getMousePosition(): { x: number; y: number } {
        const state = this.inputManager.getMouseState();
        return { x: state.x, y: state.y };
    }
    
    /**
     * 处理鼠标事件
     */
    private handleMouseEvent = (event: InputEventData): void => {
        switch (event.type) {
            case InputEventType.MOUSE_DOWN:
            case InputEventType.MOUSE_UP:
                if (event.button !== undefined) {
                    const handler = this.buttonHandlers.get(event.button);
                    if (handler) {
                        handler(event.type === InputEventType.MOUSE_DOWN);
                    }
                }
                break;
                
            case InputEventType.MOUSE_MOVE:
                if (this.moveHandler && event.clientX !== undefined && event.clientY !== undefined) {
                    this.moveHandler(event.clientX, event.clientY);
                }
                break;
                
            case InputEventType.MOUSE_WHEEL:
                if (this.wheelHandler && event.wheelDelta !== undefined) {
                    this.wheelHandler(event.wheelDelta);
                }
                break;
        }
    };
    
    /**
     * 组件销毁时清理处理器
     */
    public destroy(): void {
        this.buttonHandlers.clear();
        this.moveHandler = null;
        this.wheelHandler = null;
        super.destroy();
    }
}

/**
 * 触摸输入组件
 * 用于处理游戏对象的触摸输入
 */
export class TouchInputComponent extends InputComponent {
    private touchStartHandler: ((points: TouchPoint[]) => void) | null;
    private touchEndHandler: ((points: TouchPoint[]) => void) | null;
    private touchMoveHandler: ((points: TouchPoint[]) => void) | null;
    
    constructor(gameObject: GameObject, inputManager: InputManager) {
        super(gameObject, inputManager);
        
        this.touchStartHandler = null;
        this.touchEndHandler = null;
        this.touchMoveHandler = null;
        
        // 添加触摸事件处理器
        this.addInputHandler(InputEventType.TOUCH_START, this.handleTouchEvent);
        this.addInputHandler(InputEventType.TOUCH_END, this.handleTouchEvent);
        this.addInputHandler(InputEventType.TOUCH_MOVE, this.handleTouchEvent);
    }
    
    /**
     * 设置触摸开始处理器
     */
    public onTouchStart(handler: (points: TouchPoint[]) => void): void {
        this.touchStartHandler = handler;
    }
    
    /**
     * 设置触摸结束处理器
     */
    public onTouchEnd(handler: (points: TouchPoint[]) => void): void {
        this.touchEndHandler = handler;
    }
    
    /**
     * 设置触摸移动处理器
     */
    public onTouchMove(handler: (points: TouchPoint[]) => void): void {
        this.touchMoveHandler = handler;
    }
    
    /**
     * 获取所有活动的触摸点
     */
    public getActiveTouchPoints(): TouchPoint[] {
        return this.inputManager.getActiveTouchPoints();
    }
    
    /**
     * 处理触摸事件
     */
    private handleTouchEvent = (event: InputEventData): void => {
        if (!event.touches) return;
        
        switch (event.type) {
            case InputEventType.TOUCH_START:
                if (this.touchStartHandler) {
                    this.touchStartHandler(event.touches);
                }
                break;
                
            case InputEventType.TOUCH_END:
                if (this.touchEndHandler) {
                    this.touchEndHandler(event.touches);
                }
                break;
                
            case InputEventType.TOUCH_MOVE:
                if (this.touchMoveHandler) {
                    this.touchMoveHandler(event.touches);
                }
                break;
        }
    };
    
    /**
     * 组件销毁时清理处理器
     */
    public destroy(): void {
        this.touchStartHandler = null;
        this.touchEndHandler = null;
        this.touchMoveHandler = null;
        super.destroy();
    }
} 